home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Environments / PowerLisp 2.01 / PowerLisp 2.01 ƒ / Library / loop.lisp < prev    next >
Text File  |  1996-05-17  |  55KB  |  1,500 lines

  1. ;;;      LOOP    -*- Mode:LISP; Syntax:Common-Lisp; Package:(LOOP (COMMON-LISP); Base:10; Lowercase:T -*-
  2. ;;;      **********************************************************************
  3. ;;;      ****** Common Lisp ******** LOOP Iteration Macro *********************
  4. ;;;      **********************************************************************
  5. ;;;      **** (C) COPYRIGHT 1980, 1981 MASSACHUSETTS INSTITUTE OF TECHNOLOGY **
  6. ;;;      ******** THIS IS A READ-ONLY FILE! (ALL WRITES RESERVED) *************
  7. ;;;      **********************************************************************
  8. ;;;
  9. ;;;
  10. ;;;; LOOP Iteration Macro
  11.  
  12. ;;; This is the "officially sanctioned" version of LOOP for running in
  13. ;;; Common Lisp.  It is a conversion of LOOP 829, which is fairly close to
  14. ;;; that released with Symbolics Release 6.1 (803).     This conversion was
  15. ;;; made by Glenn Burke (one of the original author/maintainers);  the
  16. ;;; work was performed at Palladian Software, in Cambridge MA, April 1986.
  17. ;;; 
  18. ;;; The current version of this file will be maintained at MIT, available
  19. ;;; for anonymous FTP on MC.LCS.MIT.EDU from the file "LSB1;CLLOOP >".    This
  20. ;;; location will no doubt change sometime in the future.
  21. ;;; 
  22. ;;; This file, like the LOOP it is derived from, has unrestricted
  23. ;;; distribution -- anyone may take it and use it.    But for the sake of
  24. ;;; consistency, bug reporting, compatibility, and users' sanity, PLEASE
  25. ;;; PLEASE PLEASE don't go overboard with fixes or changes.     Remember that
  26. ;;; this version is supposed to be compatible with the Maclisp/Zetalisp/NIL
  27. ;;; LOOP;  it is NOT intended to be "different" or "better" or "redesigned".
  28. ;;; Report bugs and propose fixes to BUG-LOOP@MC.LCS.MIT.EDU;
  29. ;;; announcements about LOOP will be made to the mailing list
  30. ;;; INFO-LOOP@MC.LCS.MIT.EDU.  Mail concerning those lists (such as requests
  31. ;;; to be added) should be sent to the BUG-LOOP-REQUEST and
  32. ;;; INFO-LOOP-REQUEST lists respectively.  Note the Change History page
  33. ;;; below...
  34. ;;; 
  35. ;;; LOOP documentation is still probably available from the MIT Laboratory
  36. ;;; for Computer Science publications office:
  37. ;;;        LCS Publications
  38. ;;;        545 Technology Square
  39. ;;;        Cambridge, MA 02139
  40. ;;; It is Technical Memo 169, "LOOP Iteration Macro", and is very old.    The
  41. ;;; most up-to-date documentation on this version of LOOP is that in the NIL
  42. ;;; Reference Manual (TR-311 from LCS Publications);  while you wouldn't
  43. ;;; want to get that (it costs nearly $15) just for LOOP documentation,
  44. ;;; those with access to a NIL manual might photocopy the chapter on LOOP.
  45. ;;; That revised documentation can be reissued as a revised technical memo
  46. ;;; if there is sufficient demand.
  47. ;;; 
  48.  
  49. ;;;; Change History
  50. ;;; Roger Corman    15-May-96 Minor modifications for use with PowerLisp 2.0.
  51. ;;; jbs@think.com    10-Oct-86 I removed the &environment code so this would work for KCL
  52. ;;; [gsb@palladian] 30-apr-86 00:26     File Created from NIL's LOOP version 829
  53. ;;;------------------------------------------------------------------------
  54. ;;;------- End of official change history -- note local fixes below -------
  55. ;;;------------------------------------------------------------------------
  56. ;;;
  57. ;;; 
  58. ;;; bill@cambridge.apple.com 06/14/91  loop-for-arithmetic no longer assumes fixnum
  59. ;;; -------------- 2.0b2
  60. ;;; bill@cambridge.apple.com 03/04/91  string-length -> length
  61. ;;;--------------- 2.0b1
  62. ;;; bill@cambridge.apple.com 12/10/90  Add CL: prefix to the initial defpackage & in-package forms
  63. ;;; bill@cambridge.apple.com 09/28/90  define-loop-macro call goes after def of loop-translate
  64. ;;;                                       to eliminate compiler warnings.
  65. ;;; bill@cambridge.apple.com 09/07/90  PROVIDE goes at the end of the file!
  66. ;;;
  67. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  68.  
  69. ;;;; Package setup
  70.  
  71.  
  72. ;;;The following symbols are documented as being available via SI:.     Far be
  73. ;;;it for us to define a package by that name, however we can do the
  74. ;;;following.  We will create a "loop-si-kludge" package (sounds like a
  75. ;;;fairly safe name), import the SI: symbols from there into LOOP, export
  76. ;;;them, define that people (use-package 'loop), and if they want to
  77. ;;;maintain source compatibility they can add the SI nickname the
  78. ;;;loop-si-kludge package.    How's that?
  79.  
  80. ;(in-package 'loop-si-kludge)
  81.  
  82. ;(export '(loop-tequal loop-tassoc loop-tmember loop-use-system-destructuring?
  83. ;          loop-named-variable loop-simplep loop-simplep-1
  84. ;          loop-sequencer loop-sequence-elements-path))
  85.  
  86. ;(cl:defpackage loop (:use common-lisp))
  87. ;(cl:in-package :loop)
  88. (eval-when (:load-toplevel :compile-toplevel :execute)
  89.  
  90. (provide :loop)
  91. (in-package :loop)        ; no defpackage yet  RGC
  92. )
  93.  
  94. ;(use-package '(loop-si-kludge))
  95.  
  96. ;shadow?
  97.  
  98. ;(shadow '(loop loop-finish define-loop-macro define-loop-path
  99. ;               define-loop-sequence-path))
  100. ;(shadow '(loop-tequal loop-tassoc loop-tmember loop-use-system-destructuring?
  101. ;          loop-named-variable loop-simplep loop-simplep-1
  102. ;          loop-sequencer loop-sequence-elements-path))
  103.  
  104. ;(shadow '(loop:lisp)) wrong! AHR howard
  105. (shadow '(loop) 'common-lisp)  ; No shadow functions yet -- RGC
  106.  
  107.  
  108. (export '(loop loop-finish define-loop-macro define-loop-path
  109.                define-loop-sequence-path))
  110.  
  111. (export '(loop-tequal loop-tassoc loop-tmember loop-use-system-destructuring?
  112.           loop-named-variable loop-simplep loop-simplep-1
  113.           loop-sequencer loop-sequence-elements-path))
  114.  
  115. ;require?
  116.  
  117.  
  118. ;;;; Macro Environment Setup
  119.  
  120. ; Hack up the stuff for data-types.     DATA-TYPE? will always be a macro
  121. ; so that it will not require the data-type package at run time if
  122. ; all uses of the other routines are conditionalized upon that value.
  123. (eval-when (eval compile)
  124.   ; Crock for DATA-TYPE? derives from DTDCL.  We just copy it rather
  125.   ; than load it in, which requires knowing where it comes from (sigh).
  126.   ; 
  127.   (defmacro data-type? (frob)
  128.     (let ((foo (gensym)))
  129.       `((lambda (,foo)
  130.           ;; NIL croaks if nil given to GET...    No it doesn't any more!     But:
  131.           ;; Every Lisp should (but doesn't) croak if randomness given to GET
  132.           ;; LISPM croaks (of course) if randomness given to get-pname
  133.           (and (symbolp ,foo)
  134.                (or (get ,foo ':data-type)
  135.                    (and (setq ,foo (find-symbol (symbol-name ,foo) (find-package 'keyword)))
  136.                         (get ,foo ':data-type)))))
  137.         ,frob)))
  138. )
  139.  
  140. ;;; The uses of this macro are retained in the CL version of loop, in case they are
  141. ;;; needed in a particular implementation.    Originally dating from the use of the
  142. ;;; Zetalisp COPYLIST* function, this is used in situations where, were cdr-coding
  143. ;;; in use, having cdr-NIL at the end of the list might be suboptimal because the
  144. ;;; end of the list will probably be RPLACDed and so cdr-normal should be used instead.
  145. (defmacro loop-copylist* (l)
  146.   `(copy-list ,l))
  147.  
  148.  
  149. ;;;; Random Macros
  150.  
  151. (defmacro loop-simple-error (unquoted-message &optional (datum nil datump))
  152.   `(error ,(if datump "LOOP:  ~S ~A" "LOOP:  ~A")
  153.           ',unquoted-message ,@(and datump (list datum))))
  154.  
  155.  
  156. (defmacro loop-warn (unquoted-message &optional (datum nil datump))
  157.   (if datump
  158.       `(warn ,(concatenate 'string "LOOP: " unquoted-message " -- ~{~S~^ ~}")
  159.              ,datum)
  160.       `(warn ',(concatenate 'string "LOOP: " unquoted-message))))
  161.  
  162.  
  163. ;; (defmacro loop-pop-source () '(pop loop-source-code))    ;; RGC
  164.  
  165. (defun loop-pop-source ()
  166.   (if loop-source-code
  167.       (pop loop-source-code)
  168.       (error "LOOP source code ran out when another token was expected.")))
  169.  
  170.  
  171. (defmacro loop-gentemp (&optional (pref ''loopvar-))
  172.   `(gentemp (symbol-name ,pref)))
  173.  
  174.  
  175. ;;;; Setq Hackery
  176.  
  177. ; Note:     LOOP-MAKE-PSETQ is NOT flushable depending on the existence
  178. ; of PSETQ, unless PSETQ handles destructuring.     Even then it is
  179. ; preferable for the code LOOP produces to not contain intermediate
  180. ; macros, especially in the PDP10 version.
  181.  
  182. (defun loop-make-psetq (frobs)
  183.     (and frobs
  184.          (loop-make-setq
  185.             (list (car frobs)
  186.                   (if (null (cddr frobs)) (cadr frobs)
  187.                       `(prog1 ,(cadr frobs)
  188.                               ,(loop-make-psetq (cddr frobs))))))))
  189.  
  190.  
  191. (defvar loop-use-system-destructuring?
  192.     nil)
  193.  
  194. (defvar loop-desetq-temporary)
  195.  
  196. ; Do we want this???  It is, admittedly, useful...
  197. ;(defmacro loop-desetq (&rest x)
  198. ;  (let ((loop-desetq-temporary nil))
  199. ;      (let ((setq-form (loop-make-desetq x)))
  200. ;        (if loop-desetq-temporary
  201. ;            `((lambda (,loop-desetq-temporary) ,setq-form) nil)
  202. ;            setq-form))))
  203.  
  204.  
  205. (defun loop-make-desetq (x)
  206.    (if loop-use-system-destructuring?
  207.        (cons (do ((l x (cddr l))) ((null l) 'setq)
  208.                (or (and (not (null (car l))) (symbolp (car l)))
  209.                    (return 'desetq)))
  210.              x)
  211.        (do ((x x (cddr x)) (r nil) (var) (val))
  212.            ((null x) (and r (cons 'setq r)))
  213.          (setq var (car x) val (cadr x))
  214.          (cond ((and (not (atom var))
  215.                      (not (atom val))
  216.                      (not (and (member (car val) '(car cdr cadr cddr caar cdar))
  217.                                (atom (cadr val)))))
  218.                   (setq x (list* (or loop-desetq-temporary
  219.                                      (setq loop-desetq-temporary
  220.                                            (loop-gentemp 'loop-desetq-)))
  221.                                  val var loop-desetq-temporary (cddr x)))))
  222.          (setq r (nconc r (loop-desetq-internal (car x) (cadr x)))))))
  223.  
  224.  
  225. (defun loop-desetq-internal (var val)
  226.   (cond ((null var) nil)
  227.         ((atom var) (list var val))
  228.         (t (nconc (loop-desetq-internal (car var) `(car ,val))
  229.                   (loop-desetq-internal (cdr var) `(cdr ,val))))))
  230.  
  231.  
  232. (defun loop-make-setq (pairs)
  233.     (and pairs (loop-make-desetq pairs)))
  234.  
  235.  
  236. (defparameter loop-keyword-alist                        ;clause introducers
  237.      '( (named loop-do-named)
  238.         (initially loop-do-initially)
  239.         (finally loop-do-finally)
  240.         (nodeclare loop-nodeclare)
  241.         (do loop-do-do)
  242.         (doing loop-do-do)
  243.         (return loop-do-return)
  244.         (collect loop-do-collect list)
  245.         (collecting loop-do-collect list)
  246.         (append loop-do-collect append)
  247.         (appending loop-do-collect append)
  248.         (nconc loop-do-collect nconc)
  249.         (nconcing loop-do-collect nconc)
  250.         (count loop-do-collect count)
  251.         (counting loop-do-collect count)
  252.         (sum loop-do-collect sum)
  253.         (summing loop-do-collect sum)
  254.         (maximize loop-do-collect max)
  255.         (minimize loop-do-collect min)
  256.         (always loop-do-always nil) ;Normal, do always
  257.         (never loop-do-always t)    ; Negate the test on always.
  258.         (thereis loop-do-thereis)
  259.         (while loop-do-while nil while)        ; Normal, do while
  260.         (until loop-do-while t until)        ; Negate the test on while
  261.         (when loop-do-when nil when)        ; Normal, do when
  262.         (if loop-do-when nil if)    ; synonymous
  263.         (unless loop-do-when t unless)        ; Negate the test on when
  264.         (with loop-do-with)))
  265.  
  266.  
  267. (defparameter loop-iteration-keyword-alist
  268.     `((for loop-do-for)
  269.       (as loop-do-for)
  270.       (repeat loop-do-repeat)))
  271.  
  272.  
  273. (defparameter loop-for-keyword-alist                    ;Types of FOR
  274.      '( (= loop-for-equals)
  275.         (first loop-for-first)
  276.         (in loop-list-stepper car)
  277.         (on loop-list-stepper nil)
  278.         (from loop-for-arithmetic from)
  279.         (downfrom loop-for-arithmetic downfrom)
  280.         (upfrom loop-for-arithmetic upfrom)
  281.         (below loop-for-arithmetic below)
  282.         (to loop-for-arithmetic to)
  283.         (being loop-for-being)))
  284.  
  285. (defvar loop-prog-names)
  286.  
  287.  
  288. (defvar loop-macro-environment) ;Second arg to macro functions,
  289.                                         ;passed to macroexpand.
  290.  
  291. (defvar loop-path-keyword-alist nil)            ; PATH functions
  292. (defvar loop-named-variables)                    ; see LOOP-NAMED-VARIABLE
  293. (defvar loop-variables)                    ;Variables local to the loop
  294. (defvar loop-declarations)                        ; Local dcls for above
  295. (defvar loop-nodeclare)                    ; but don't declare these
  296. (defvar loop-variable-stack)
  297. (defvar loop-declaration-stack)
  298. (defvar loop-desetq-crocks)                        ; see loop-make-variable
  299. (defvar loop-desetq-stack)                        ; and loop-translate-1
  300. (defvar loop-prologue)                            ;List of forms in reverse order
  301. (defvar loop-wrappers)                            ;List of wrapping forms, innermost first
  302. (defvar loop-before-loop)
  303. (defvar loop-body)                                ;..
  304. (defvar loop-after-body)                        ;.. for FOR steppers
  305. (defvar loop-epilogue)                            ;..
  306. (defvar loop-after-epilogue)                    ;So COLLECT's RETURN comes after FINALLY
  307. (defvar loop-conditionals)                        ;If non-NIL, condition for next form in body
  308.   ;The above is actually a list of entries of the form
  309.   ;(cond (condition forms...))
  310.   ;When it is output, each successive condition will get
  311.   ;nested inside the previous one, but it is not built up
  312.   ;that way because you wouldn't be able to tell a WHEN-generated
  313.   ;COND from a user-generated COND.
  314.   ;When ELSE is used, each cond can get a second clause
  315.  
  316. (defvar loop-when-it-variable)                    ;See LOOP-DO-WHEN
  317. (defvar loop-never-stepped-variable)            ; see LOOP-FOR-FIRST
  318. (defvar loop-emitted-body?)                        ; see LOOP-EMIT-BODY,
  319.                                                 ; and LOOP-DO-FOR
  320. (defvar loop-iteration-variables)                ; LOOP-MAKE-ITERATION-VARIABLE
  321. (defvar loop-iteration-variablep)                ; ditto
  322. (defvar loop-collect-cruft)                        ; for multiple COLLECTs (etc)
  323. (defvar loop-source-code)
  324. (defvar loop-duplicate-code nil)  ; see LOOP-OPTIMIZE-DUPLICATED-CODE-ETC
  325.  
  326.  
  327. ;;;; Construct a value return
  328.  
  329.  
  330. (defun loop-construct-return (form)
  331.   (if loop-prog-names
  332.       `(return-from ,(car loop-prog-names) ,form)
  333.       `(return ,form)))
  334.  
  335. ;;;; Token Hackery
  336.  
  337. ;Compare two "tokens".    The first is the frob out of LOOP-SOURCE-CODE,
  338. ;the second a symbol to check against.
  339.  
  340. (defun loop-tequal (x1 x2)
  341.   (and (symbolp x1) (string= x1 x2)))
  342.  
  343.  
  344. (defun loop-tassoc (kwd alist)
  345.   (and (symbolp kwd) (assoc kwd alist :test #'string=)))
  346.  
  347.  
  348. (defun loop-tmember (kwd list)
  349.   (and (symbolp kwd) (member kwd list :test #'string=)))
  350.  
  351. (defmacro define-loop-macro (keyword)
  352.   "Makes KEYWORD, which is a LOOP keyword, into a Lisp macro that may
  353. introduce a LOOP form.    This facility exists mostly for diehard users of
  354. a predecessor of LOOP.    Unconstrained use is not advised, as it tends to
  355. decrease the transportability of the code and needlessly uses up a
  356. function name."
  357.   (or (eq keyword 'loop)
  358.       (loop-tassoc keyword loop-keyword-alist)
  359.       (loop-tassoc keyword loop-iteration-keyword-alist)
  360.       (loop-simple-error "not a loop keyword - define-loop-macro" keyword))
  361. ;  #-kcl    ; this doesn't work -- RGC
  362. ;  `(progn
  363. ;     (defmacro ,keyword (&whole whole-form &rest keywords-and-args &environment env)
  364. ;       (declare (ignore keywords-and-args))
  365. ;       (loop-translate whole-form env))
  366. ;;    #+symbolics  ;; tab correctly
  367. ;;     (pushnew '(loop . zwei:indent-loop) zwei:*lisp-indent-offset-alist* :test #'equal)
  368. ;     )
  369. ;  #+kcl    ; this doesn't work -- RGC
  370.   `(setf (macro-function ',keyword)
  371.          #'(lambda (whole-form &optional env)    ;; RGC  (added &optional)
  372.              (loop-translate whole-form env))))
  373.  
  374.  
  375. (defmacro loop-finish () 
  376.   "Causes the iteration to terminate \"normally\", the same as implicit
  377. termination by an iteration driving clause, or by use of WHILE or
  378. UNTIL -- the epilogue code (if any) will be run, and any implicitly
  379. collected result will be returned as the value of the LOOP."
  380.   '(go end-loop))
  381.  
  382. (defun loop-translate (x loop-macro-environment)
  383.   (loop-translate-1 x))
  384.  
  385. ;;(let ((ccl::*warn-if-redefine-kernel* nil)
  386. ;;      (ccl::*warn-if-redefine* nil))
  387. (define-loop-macro loop)
  388.  
  389.  
  390. (defun loop-end-testify (list-of-forms)
  391.     (if (null list-of-forms) nil
  392.         `(when ,(if (null (cdr (setq list-of-forms (nreverse list-of-forms))))
  393.                     (car list-of-forms)
  394.                     (cons 'or list-of-forms))
  395.            (go end-loop))))
  396.  
  397. (defun loop-optimize-duplicated-code-etc (&aux before after groupa groupb a b
  398.                                                lastdiff)
  399.     (do ((l1 (nreverse loop-before-loop) (cdr l1))
  400.          (l2 (nreverse loop-after-body) (cdr l2)))
  401.         ((equal l1 l2)
  402.            (setq loop-body (nconc (delete nil l1) (nreverse loop-body))))
  403.       (push (car l1) before) (push (car l2) after))
  404.     (cond ((not (null loop-duplicate-code))
  405.              (setq loop-before-loop (nreverse (delete nil before))
  406.                    loop-after-body (nreverse (delete nil after))))
  407.           (t (setq loop-before-loop nil loop-after-body nil
  408.                    before (nreverse before) after (nreverse after))
  409.              (do ((bb before (cdr bb)) (aa after (cdr aa)))
  410.                  ((null aa))
  411.                (cond ((not (equal (car aa) (car bb))) (setq lastdiff aa))
  412.                      ((not (loop-simplep (car aa)))        ;Mustn't duplicate
  413.                       (return nil))))
  414.              (cond (lastdiff  ;Down through lastdiff should be duplicated
  415.                     (do nil (nil)
  416.                       (and (car before) (push (car before) loop-before-loop))
  417.                       (and (car after) (push (car after) loop-after-body))
  418.                       (setq before (cdr before) after (cdr after))
  419.                       (and (eq after (cdr lastdiff)) (return nil)))
  420.                     (setq loop-before-loop (nreverse loop-before-loop)
  421.                           loop-after-body (nreverse loop-after-body))))
  422.              (do ((bb (nreverse before) (cdr bb))
  423.                   (aa (nreverse after) (cdr aa)))
  424.                  ((null aa))
  425.                (setq a (car aa) b (car bb))
  426.                (cond ((and (null a) (null b)))
  427.                      ((equal a b)
  428.                         (loop-output-group groupb groupa)
  429.                         (push a loop-body)
  430.                         (setq groupb nil groupa nil))
  431.                      (t (and a (push a groupa)) (and b (push b groupb)))))
  432.              (loop-output-group groupb groupa)))
  433.     (and loop-never-stepped-variable
  434.          (push `(setq ,loop-never-stepped-variable nil) loop-after-body))
  435.     nil)
  436.  
  437.  
  438. (defun loop-output-group (before after)
  439.     (and (or after before)
  440.          (let ((v (or loop-never-stepped-variable
  441.                       (setq loop-never-stepped-variable
  442.                             (loop-make-variable
  443.                               (loop-gentemp 'loop-iter-flag-) t nil)))))
  444.             (push (cond ((not before)
  445.                           `(unless ,v (progn ,@after)))
  446.                         ((not after)
  447.                           `(when ,v (progn ,@before)))
  448.                         (t `(cond (,v ,@before) (t ,@after))))
  449.                   loop-body))))
  450.  
  451.  
  452. (defun loop-translate-1 (loop-source-code-form)
  453.   (let ((loop-source-code loop-source-code-form))
  454.   (and (eq (car loop-source-code) 'loop)
  455.        (setq loop-source-code (cdr loop-source-code)))
  456.   (do ((loop-iteration-variables nil)
  457.        (loop-iteration-variablep nil)
  458.        (loop-variables nil)
  459.        (loop-nodeclare nil)
  460.        (loop-named-variables nil)
  461.        (loop-declarations nil)
  462.        (loop-desetq-crocks nil)
  463.        (loop-variable-stack nil)
  464.        (loop-declaration-stack nil)
  465.        (loop-desetq-stack nil)
  466.        (loop-prologue nil)
  467.        (loop-wrappers nil)
  468.        (loop-before-loop nil)
  469.        (loop-body nil)
  470.        (loop-emitted-body? nil)
  471.        (loop-after-body nil)
  472.        (loop-epilogue nil)
  473.        (loop-after-epilogue nil)
  474.        (loop-conditionals nil)
  475.        (loop-when-it-variable nil)
  476.        (loop-never-stepped-variable nil)
  477.        (loop-desetq-temporary nil)
  478.        (loop-prog-names nil)
  479.        (loop-collect-cruft nil)
  480.        (keyword)
  481.        (tem)
  482.        (progvars))
  483.       ((null loop-source-code)
  484.        (and loop-conditionals
  485.             (loop-simple-error "Hanging conditional in loop macro"
  486.                                (caadar loop-conditionals)))
  487.        (loop-optimize-duplicated-code-etc)
  488.        (loop-bind-block)
  489.        (and loop-desetq-temporary (push loop-desetq-temporary progvars))
  490.        (setq tem `(block ,(car loop-prog-names)
  491.                     (let ,progvars
  492.                       (tagbody
  493.                         ,@(nreverse loop-prologue)
  494.                         ,@loop-before-loop
  495.                      next-loop
  496.                         ,@loop-body
  497.                         ,@loop-after-body
  498.                         (go next-loop)
  499.                         (go end-loop)
  500.                      end-loop
  501.                         ,@(nreverse loop-epilogue)
  502.                         ,@(nreverse loop-after-epilogue)))))
  503.        (do ((vars) (dcls) (crocks))
  504.            ((null loop-variable-stack))
  505.          (setq vars (car loop-variable-stack)
  506.                loop-variable-stack (cdr loop-variable-stack)
  507.                dcls (car loop-declaration-stack)
  508.                loop-declaration-stack (cdr loop-declaration-stack)
  509.                tem (list tem))
  510.          (and (setq crocks (pop loop-desetq-stack))
  511.               (push (loop-make-desetq crocks) tem))
  512.          (and dcls (push (cons 'declare dcls) tem))
  513.          (cond ((do ((l vars (cdr l))) ((null l) nil)
  514.                   (and (not (atom (car l)))
  515.                        (or (null (caar l)) (not (symbolp (caar l))))
  516.                        (return t)))
  517.                   (setq tem `(let ,(nreverse vars) ,@tem)))
  518.                (t (let ((lambda-vars nil) (lambda-vals nil))
  519.                     (do ((l vars (cdr l)) (v)) ((null l))
  520.                       (cond ((atom (setq v (car l)))
  521.                                (push v lambda-vars)
  522.                                (push nil lambda-vals))
  523.                             (t (push (car v) lambda-vars)
  524.                                (push (cadr v) lambda-vals))))
  525.                     (setq tem `((lambda ,lambda-vars ,@tem)
  526.                                 ,@lambda-vals))))))
  527.        (do ((l loop-wrappers (cdr l))) ((null l))
  528.          (setq tem (append (car l) (list tem))))
  529.        tem)
  530.     ;;The following commented-out code is what comes from the newest source
  531.     ;; code in use in NIL.    The code in use following it comes from about version
  532.     ;; 803, that in use in symbolics release 6.1, for instance.     To turn on the
  533.     ;; implicit DO feature, switch them and fix loop-get-form to just pop the source.
  534.     (if (symbolp (setq keyword (car loop-source-code)))
  535.         (loop-pop-source)
  536.       (setq keyword 'do))
  537.     (if (setq tem (loop-tassoc keyword loop-keyword-alist))
  538.         (apply (cadr tem) (cddr tem))
  539.         (if (setq tem (loop-tassoc
  540.                          keyword loop-iteration-keyword-alist))
  541.             (loop-hack-iteration tem)
  542.             (if (loop-tmember keyword '(and else))
  543.                 ; Alternative is to ignore it, ie let it go around to the
  544.                 ; next keyword...
  545.                 (loop-simple-error
  546.                    "secondary clause misplaced at top level in LOOP macro"
  547.                    (list keyword (car loop-source-code)
  548.                          (cadr loop-source-code)))
  549.                 (loop-simple-error
  550.                    "unknown keyword in LOOP macro" keyword))))
  551. )))
  552.  
  553.  
  554. (defun loop-bind-block ()
  555.    (cond ((not (null loop-variables))
  556.             (push loop-variables loop-variable-stack)
  557.             (push loop-declarations loop-declaration-stack)
  558.             (setq loop-variables nil loop-declarations nil)
  559.             (push loop-desetq-crocks loop-desetq-stack)
  560.             (setq loop-desetq-crocks nil))))
  561.  
  562.  
  563. ;Get FORM argument to a keyword.  Read up to atom.    PROGNify if necessary.
  564. (defun loop-get-progn-1 ()
  565.   (do ((forms (list (loop-pop-source)) (cons (loop-pop-source) forms))
  566.        (nextform (car loop-source-code) (car loop-source-code)))
  567.       ((atom nextform) (nreverse forms))))
  568.  
  569. (defun loop-get-progn ()
  570.   (let ((forms (loop-get-progn-1)))
  571.     (if (null (cdr forms)) (car forms) (cons 'progn forms))))
  572.  
  573. (defun loop-get-form (for)
  574.   ;; Until implicit DO is installed, use the following.     Then, replace it with
  575.   ;; just loop-pop-source.
  576.   (let ((forms (loop-get-progn-1)))
  577.     (cond ((null (cdr forms)) (car forms))
  578.           (t (loop-warn 
  579. "The use of multiple forms with an implicit PROGN in this context
  580. is considered obsolete, but is still supported for the time being.
  581. If you did not intend to use multiple forms here, you probably omitted a DO.
  582. If the use of multiple forms was intentional, put a PROGN in your code.
  583. The offending clause"
  584.                 (if (atom for) (cons for forms) (append for forms)))
  585.              (cons 'progn forms)))))
  586.  
  587.  
  588. ;;;This function takes a substitutable expression containing generic arithmetic
  589. ;;; of some form or another, and a data type name, and substitutes for the function
  590. ;;; any type-specific functions for that type in the implementation.
  591. (defun loop-typed-arith (substitutable-expression data-type)
  592.   (declare (ignore data-type))
  593.   substitutable-expression)
  594.  
  595. (defvar loop-floating-point-types
  596.         '(flonum float short-float single-float double-float long-float))
  597.  
  598. (defun loop-typed-init (data-type)
  599.   (let ((tem nil))
  600.     (cond ((data-type? data-type) (initial-value data-type))
  601.           ((loop-tmember data-type '(fixnum integer number)) 0)
  602.           ((setq tem (car (loop-tmember
  603.                             data-type loop-floating-point-types)))
  604.            (cond ((member tem '(flonum float)) 0.0)
  605.                  (t (coerce 0 tem)))))))
  606.  
  607.  
  608. (defun loop-make-variable (name initialization dtype)
  609.   (cond ((null name)
  610.            (cond ((not (null initialization))
  611.                     (push (list (setq name (loop-gentemp 'loop-ignore-))
  612.                                 initialization)
  613.                           loop-variables)
  614.                       (push `(ignore ,name) loop-declarations))))
  615.         ((atom name)
  616.            (cond (loop-iteration-variablep
  617.                     (if (member name loop-iteration-variables)
  618.                         (loop-simple-error
  619.                            "Duplicated iteration variable somewhere in LOOP"
  620.                            name)
  621.                         (push name loop-iteration-variables)))
  622.                  ((assoc name loop-variables)
  623.                     (loop-simple-error
  624.                        "Duplicated var in LOOP bind block" name)))
  625.            (or (symbolp name)
  626.                (loop-simple-error "Bad variable somewhere in LOOP" name))
  627.            (loop-declare-variable name dtype)
  628.            ; We use ASSOC on this list to check for duplications (above),
  629.            ; so don't optimize out this list:
  630.            (push (list name (or initialization (loop-typed-init dtype)))
  631.                  loop-variables))
  632.         (initialization
  633.            (cond (loop-use-system-destructuring?
  634.                     (loop-declare-variable name dtype)
  635.                     (push (list name initialization) loop-variables))
  636.                  (t (let ((newvar (loop-gentemp 'loop-destructure-)))
  637.                       (push (list newvar initialization) loop-variables)
  638.                       ; LOOP-DESETQ-CROCKS gathered in reverse order.
  639.                       (setq loop-desetq-crocks
  640.                             (list* name newvar loop-desetq-crocks))
  641.                       (loop-make-variable name nil dtype)))))
  642.         (t (let ((tcar nil) (tcdr nil))
  643.              (if (atom dtype) (setq tcar (setq tcdr dtype))
  644.                (setq tcar (car dtype) tcdr (cdr dtype)))
  645.              (loop-make-variable (car name) nil tcar)
  646.              (loop-make-variable (cdr name) nil tcdr))))
  647.   name)
  648.  
  649.  
  650. (defun loop-make-iteration-variable (name initialization dtype)
  651.     (let ((loop-iteration-variablep t))
  652.        (loop-make-variable name initialization dtype)))
  653.  
  654.  
  655. (defun loop-declare-variable (name dtype)
  656.     (cond ((or (null name) (null dtype)) nil)
  657.           ((symbolp name)
  658.              (cond ((member name loop-nodeclare))
  659.                    ((data-type? dtype)
  660.                       (setq loop-declarations
  661.                             (append (variable-declarations dtype name)
  662.                                     loop-declarations)))
  663.                    (t (push `(type ,dtype ,name) loop-declarations))))
  664.           ((consp name)
  665.               (cond ((consp dtype)
  666.                        (loop-declare-variable (car name) (car dtype))
  667.                        (loop-declare-variable (cdr name) (cdr dtype)))
  668.                     (t (loop-declare-variable (car name) dtype)
  669.                        (loop-declare-variable (cdr name) dtype))))
  670.           (t (loop-simple-error "can't hack this"
  671.                                 (list 'loop-declare-variable name dtype)))))
  672.  
  673.  
  674. (defun loop-constantp (form)
  675.   (constantp form))
  676.  
  677. (defun loop-maybe-bind-form (form data-type?)
  678.     ; Consider implementations which will not keep EQ quoted constants
  679.     ; EQ after compilation & loading.
  680.     ; Note FUNCTION is not hacked, multiple occurences might cause the
  681.     ; compiler to break the function off multiple times!
  682.     ; Hacking it probably isn't too important here anyway.    The ones that
  683.     ; matter are the ones that use it as a stepper (or whatever), which
  684.     ; handle it specially.
  685.     (if (loop-constantp form) form
  686.         (loop-make-variable (loop-gentemp 'loop-bind-) form data-type?)))
  687.  
  688.  
  689. (defun loop-optional-type ()
  690.     (let ((token (car loop-source-code)))
  691.         (and (not (null token))
  692.              (or (not (atom token))
  693.                  (data-type? token)
  694.                  (loop-tmember token '(fixnum integer number notype))
  695.                  (loop-tmember token loop-floating-point-types))
  696.              (loop-pop-source))))
  697.  
  698.  
  699. ;Incorporates conditional if necessary
  700. (defun loop-make-conditionalization (form)
  701.   (cond ((not (null loop-conditionals))
  702.            (rplacd (last (car (last (car (last loop-conditionals)))))
  703.                    (list form))
  704.            (cond ((loop-tequal (car loop-source-code) 'and)
  705.                     (loop-pop-source)
  706.                     nil)
  707.                  ((loop-tequal (car loop-source-code) 'else)
  708.                     (loop-pop-source)
  709.                     ;; If we are already inside an else clause, close it off
  710.                     ;; and nest it inside the containing when clause
  711.                     (let ((innermost (car (last loop-conditionals))))
  712.                       (cond ((null (cddr innermost)))    ;Now in a WHEN clause, OK
  713.                             ((null (cdr loop-conditionals))
  714.                              (loop-simple-error "More ELSEs than WHENs"
  715.                                                 (list 'else (car loop-source-code)
  716.                                                       (cadr loop-source-code))))
  717.                             (t (setq loop-conditionals (cdr (nreverse loop-conditionals)))
  718.                                (rplacd (last (car (last (car loop-conditionals))))
  719.                                        (list innermost))
  720.                                (setq loop-conditionals (nreverse loop-conditionals)))))
  721.                     ;; Start a new else clause
  722.                     (rplacd (last (car (last loop-conditionals)))
  723.                             (list (list 't)))
  724.                     nil)
  725.                  (t ;Nest up the conditionals and output them
  726.                      (do ((prev (car loop-conditionals) (car l))
  727.                           (l (cdr loop-conditionals) (cdr l)))
  728.                          ((null l))
  729.                        (rplacd (last (car (last prev))) (list (car l))))
  730.                      (prog1 (car loop-conditionals)
  731.                             (setq loop-conditionals nil)))))
  732.         (t form)))
  733.  
  734. (defun loop-pseudo-body (form &aux (z (loop-make-conditionalization form)))
  735.    (cond ((not (null z))
  736.             (cond (loop-emitted-body? (push z loop-body))
  737.                   (t (push z loop-before-loop) (push z loop-after-body))))))
  738.  
  739. (defun loop-emit-body (form)
  740.   (setq loop-emitted-body? t)
  741.   (loop-pseudo-body form))
  742.  
  743.  
  744. (defun loop-do-named ()
  745.   (let ((name (loop-pop-source)))
  746.     (unless (and name (symbolp name))
  747.       (loop-simple-error "Bad name for your loop construct" name))
  748.     ;If this don't come first, LOOP will be confused about how to return
  749.     ; from the prog when it tries to generate such code
  750.     (when (or loop-before-loop loop-body loop-after-epilogue)
  751.       (loop-simple-error "NAMED clause occurs too late" name))
  752.     (when (cdr (setq loop-prog-names (cons name loop-prog-names)))
  753.       (loop-simple-error "Too many names for your loop construct"
  754.                          loop-prog-names))))
  755.  
  756. (defun loop-do-initially ()
  757.   (push (loop-get-progn) loop-prologue))
  758.  
  759. (defun loop-nodeclare (&aux (varlist (loop-pop-source)))
  760.     (or (null varlist)
  761.         (consp varlist)
  762.         (loop-simple-error "Bad varlist to nodeclare loop clause" varlist))
  763.     (setq loop-nodeclare (append varlist loop-nodeclare)))
  764.  
  765. (defun loop-do-finally ()
  766.   (push (loop-get-progn) loop-epilogue))
  767.  
  768. (defun loop-do-do ()
  769.   (loop-emit-body (loop-get-progn)))
  770.  
  771. (defun loop-do-return ()
  772.    (loop-pseudo-body (loop-construct-return (loop-get-form 'return))))
  773.  
  774.  
  775.  
  776.  
  777. (defun loop-do-collect (type)
  778.   (let ((var nil) (form nil) (tem nil) (tail nil) (dtype nil) (cruft nil) (rvar nil)
  779.         (ctype (case type
  780.                  ((max min) 'maxmin)
  781.                  ((nconc list append) 'list)
  782.                  ((count sum) 'sum)
  783. ;                 ((member type '(max min)) 'maxmin)
  784.                  (t (error "LOOP internal error:  ~S is an unknown collecting keyword."
  785.                            type)))))
  786.     (setq form (loop-get-form type) dtype (loop-optional-type))
  787.     (cond ((loop-tequal (car loop-source-code) 'into)
  788.              (loop-pop-source)
  789.              (setq rvar (setq var (loop-pop-source)))))
  790.     ; CRUFT will be (varname ctype dtype var tail (optional tem))
  791.     (cond ((setq cruft (assoc var loop-collect-cruft))
  792.              (cond ((not (eq ctype (car (setq cruft (cdr cruft)))))
  793.                       (loop-simple-error
  794.                          "incompatible LOOP collection types"
  795.                          (list ctype (car cruft))))
  796.                    ((and dtype (not (eq dtype (cadr cruft))))
  797.                       ;Conditional should be on data-type reality
  798.                     (error "~A and ~A Unequal data types into ~A"
  799.                            dtype (cadr cruft) (car cruft))))
  800.              (setq dtype (car (setq cruft (cdr cruft)))
  801.                    var (car (setq cruft (cdr cruft)))
  802.                    tail (car (setq cruft (cdr cruft)))
  803.                    tem (cadr cruft))
  804.              (and (eq ctype 'maxmin)
  805.                   (not (atom form)) (null tem)
  806.                   (rplaca (cdr cruft)
  807.                           (setq tem (loop-make-variable
  808.                                        (loop-gentemp 'loop-maxmin-)
  809.                                        nil dtype)))))
  810.           (t (unless dtype
  811.                (setq dtype (case type
  812.                              (count 'fixnum)
  813.                              ((min max sum) 'number))))
  814.              (unless var
  815.                (push (loop-construct-return (setq var (loop-gentemp)))
  816.                      loop-after-epilogue))
  817.              (loop-make-iteration-variable var nil dtype)
  818.              (cond ((eq ctype 'maxmin)
  819.                       ;Make a temporary.
  820.                       (unless (atom form)
  821.                         (setq tem (loop-make-variable
  822.                                     (loop-gentemp) nil dtype)))
  823.                       ;Use the tail slot of the collect database to hold a
  824.                       ; flag which says we have been around once already.
  825.                       (setq tail (loop-make-variable
  826.                                    (loop-gentemp 'loop-maxmin-fl-) t nil)))
  827.                    ((eq ctype 'list)
  828.                     ;For dumb collection, we need both a tail and a flag var
  829.                     ; to tell us whether we have iterated.
  830.                     (setq tail (loop-make-variable (loop-gentemp) nil nil)
  831.                           tem (loop-make-variable (loop-gentemp) nil nil))))
  832.              (push (list rvar ctype dtype var tail tem)
  833.                    loop-collect-cruft)))
  834.     (loop-emit-body
  835.         (case type
  836.           (count (setq tem `(setq ,var (,(loop-typed-arith '1+ dtype)
  837.                                         ,var)))
  838.                  (if (or (eq form t) (equal form ''t))
  839.                      tem
  840.                      `(when ,form ,tem)))
  841.           (sum `(setq ,var (,(loop-typed-arith '+ dtype) ,form ,var)))
  842.           ((max min)
  843.              (let ((forms nil) (arglist nil))
  844.                 ; TEM is temporary, properly typed.
  845.                 (and tem (setq forms `((setq ,tem ,form)) form tem))
  846.                 (setq arglist (list var form))
  847.                 (push (if (loop-tmember dtype '(fixnum flonum))
  848.                           ; no contagious arithmetic
  849.                           `(when (or ,tail
  850.                                      (,(loop-typed-arith
  851.                                          (if (eq type 'max) '< '>)
  852.                                          dtype)
  853.                                       ,@arglist))
  854.                              (setq ,tail nil ,@arglist))
  855.                           ; potentially contagious arithmetic -- must use
  856.                           ; MAX or MIN so that var will be contaminated
  857.                           `(setq ,var (cond (,tail (setq ,tail nil) ,form)
  858.                                             (t (,type ,@arglist)))))
  859.                       forms)
  860.                 (if (cdr forms) (cons 'progn (nreverse forms)) (car forms))))
  861.           (t (case type
  862.                 (list (setq form (list 'list form)))
  863.                 (append (or (and (not (atom form)) (eq (car form) 'list))
  864.                             (setq form `(copy-list ,form)))))
  865.              (let ((q `(if ,tail (cdr (rplacd ,tail ,tem))
  866.                          (setq ,var ,tem))))
  867.                 (if (and (not (atom form)) (eq (car form) 'list) (cdr form))
  868.                     `(setq ,tem ,form ,tail ,(loop-cdrify (cddr form) q))
  869.                     `(when (setq ,tem ,form) (setq ,tail (last ,q))))))))))
  870.  
  871.  
  872. (defun loop-cdrify (arglist form)
  873.     (do ((size (length arglist) (- size 4)))
  874.         ((< size 4)
  875.          (if (zerop size) form
  876.              (list (cond ((= size 1) 'cdr) ((= size 2) 'cddr) (t 'cdddr))
  877.                    form)))
  878.       (declare (type fixnum size))
  879.       (setq form (list 'cddddr form))))
  880.  
  881.  
  882.  
  883. (defun loop-do-while (negate? kwd &aux (form (loop-get-form kwd)))
  884.   (and loop-conditionals (loop-simple-error
  885.                            "not allowed inside LOOP conditional"
  886.                            (list kwd form)))
  887.   (loop-pseudo-body `(,(if negate? 'when 'unless)
  888.                       ,form (go end-loop))))
  889.  
  890.  
  891. (defun loop-do-when (negate? kwd)
  892.   (let ((form (loop-get-form kwd)) (cond nil))
  893.     (cond ((loop-tequal (cadr loop-source-code) 'it)
  894.              ;WHEN foo RETURN IT and the like
  895.              (setq cond `(setq ,(loop-when-it-variable) ,form))
  896.              (setq loop-source-code                ;Plug in variable for IT
  897.                    (list* (car loop-source-code)
  898.                           loop-when-it-variable
  899.                           (cddr loop-source-code))))
  900.           (t (setq cond form)))
  901.     (and negate? (setq cond `(not ,cond)))
  902.     (setq loop-conditionals (nconc loop-conditionals `((cond (,cond)))))))
  903.  
  904. (defun loop-do-with ()
  905.   (do ((var) (equals) (val) (dtype)) (nil)
  906.     (setq var (loop-pop-source) equals (car loop-source-code))
  907.     (cond ((loop-tequal equals '=)
  908.              (loop-pop-source)
  909.              (setq val (loop-get-form (list 'with var '=)) dtype nil))
  910.           ((or (loop-tequal equals 'and)
  911.                (loop-tassoc equals loop-keyword-alist)
  912.                (loop-tassoc equals loop-iteration-keyword-alist))
  913.              (setq val nil dtype nil))
  914.           (t (setq dtype (loop-optional-type) equals (car loop-source-code))
  915.              (cond ((loop-tequal equals '=)
  916.                       (loop-pop-source)
  917.                       (setq val (loop-get-form (list 'with var dtype '=))))
  918.                    ((and (not (null loop-source-code))
  919.                          (not (loop-tassoc equals loop-keyword-alist))
  920.                          (not (loop-tassoc
  921.                                  equals loop-iteration-keyword-alist))
  922.                          (not (loop-tequal equals 'and)))
  923.                       (loop-simple-error "Garbage where = expected" equals))
  924.                    (t (setq val nil)))))
  925.     (loop-make-variable var val dtype)
  926.     (if (not (loop-tequal (car loop-source-code) 'and)) (return nil)
  927.         (loop-pop-source)))
  928.   (loop-bind-block))
  929.  
  930. (defun loop-do-always (negate?)
  931.   (let ((form (loop-get-form 'always)))
  932.     (loop-emit-body `(,(if negate? 'when 'unless) ,form
  933.                       ,(loop-construct-return nil)))
  934.     (push (loop-construct-return t) loop-after-epilogue)))
  935.  
  936. ;THEREIS expression
  937. ;If expression evaluates non-nil, return that value.
  938. (defun loop-do-thereis ()
  939.    (loop-emit-body `(when (setq ,(loop-when-it-variable)
  940.                                 ,(loop-get-form 'thereis))
  941.                       ,(loop-construct-return loop-when-it-variable))))
  942.  
  943.  
  944. ;;;; Hacks
  945.  
  946. (defun loop-simplep (expr)
  947.     (if (null expr) 0
  948.       (catch 'loop-simplep
  949.         (let ((ans (loop-simplep-1 expr)))
  950.           (declare (type fixnum ans))
  951.           (and (< ans 20.) ans)))))
  952.  
  953. (defvar loop-simplep
  954.         '(> < <= >= /= + - 1+ 1- ash equal atom setq prog1 prog2 and or = aref char schar sbit svref))
  955.  
  956. (defun loop-simplep-1 (x)
  957.   (let ((z 0))
  958.     (declare (type fixnum z))
  959.     (cond ((loop-constantp x) 0)
  960.           ((atom x) 1)
  961.           ((eq (car x) 'cond)
  962.              (do ((cl (cdr x) (cdr cl))) ((null cl))
  963.                (do ((f (car cl) (cdr f))) ((null f))
  964.                  (setq z (+ (loop-simplep-1 (car f)) z 1))))
  965.              z)
  966.           ((symbolp (car x))
  967.              (let ((fn (car x)) (tem nil))
  968.                (cond ((setq tem (get fn 'loop-simplep))
  969.                         (if (typep tem 'fixnum) (setq z tem)
  970.                             (setq z (funcall tem x) x nil)))
  971.                      ((member fn '(null not eq go return progn)))
  972.                      ((member fn '(car cdr)) (setq z 1))
  973.                      ((member fn '(caar cadr cdar cddr)) (setq z 2))
  974.                      ((member fn '(caaar caadr cadar caddr
  975.                                    cdaar cdadr cddar cdddr))
  976.                         (setq z 3))
  977.                      ((member fn '(caaaar caaadr caadar caaddr
  978.                                    cadaar cadadr caddar cadddr
  979.                                    cdaaar cdaadr cdadar cdaddr
  980.                                    cddaar cddadr cdddar cddddr))
  981.                         (setq z 4))
  982.                      ((member fn loop-simplep) (setq z 2))
  983.                      (t (multiple-value-bind (new-form expanded-p)
  984.                               (macroexpand-1 x loop-macro-environment)
  985.                           (if expanded-p
  986.                               (setq z (loop-simplep-1 new-form) x nil)
  987.                             (throw 'loop-simplep nil)))))
  988.                (do ((l (cdr x) (cdr l))) ((null l))
  989.                  (setq z (+ (loop-simplep-1 (car l)) 1 z)))
  990.                z))
  991.           (t (throw 'loop-simplep nil)))))
  992.  
  993.  
  994. ;;;; The iteration driver
  995. (defun loop-hack-iteration (entry)
  996.   (do ((last-entry entry)
  997.        (source loop-source-code loop-source-code)
  998.        (pre-step-tests nil)
  999.        (steps nil)
  1000.        (post-step-tests nil)
  1001.        (pseudo-steps nil)
  1002.        (pre-loop-pre-step-tests nil)
  1003.        (pre-loop-steps nil)
  1004.        (pre-loop-post-step-tests nil)
  1005.        (pre-loop-pseudo-steps nil)
  1006.        (tem) (data) (foo) (bar))
  1007.       (nil)
  1008.     ; Note we collect endtests in reverse order, but steps in correct
  1009.     ; order.  LOOP-END-TESTIFY does the nreverse for us.
  1010.     (setq tem (setq data (apply (cadr entry) (cddr entry))))
  1011.     (and (car tem) (push (car tem) pre-step-tests))
  1012.     (setq steps (nconc steps (loop-copylist* (car (setq tem (cdr tem))))))
  1013.     (and (car (setq tem (cdr tem))) (push (car tem) post-step-tests))
  1014.     (setq pseudo-steps
  1015.           (nconc pseudo-steps (loop-copylist* (car (setq tem (cdr tem))))))
  1016.     (setq tem (cdr tem))
  1017.     (and (or loop-conditionals loop-emitted-body?)
  1018.          (or tem pre-step-tests post-step-tests pseudo-steps)
  1019.          (let ((cruft (list (car entry) (car source)
  1020.                             (cadr source) (caddr source))))
  1021.             (if loop-emitted-body?
  1022.                 (loop-simple-error
  1023.                    "Iteration is not allowed to follow body code" cruft)
  1024.                 (loop-simple-error
  1025.                    "Iteration starting inside of conditional in LOOP"
  1026.                    cruft))))
  1027.     (or tem (setq tem data))
  1028.     (and (car tem) (push (car tem) pre-loop-pre-step-tests))
  1029.     (setq pre-loop-steps
  1030.           (nconc pre-loop-steps (loop-copylist* (car (setq tem (cdr tem))))))
  1031.     (and (car (setq tem (cdr tem))) (push (car tem) pre-loop-post-step-tests))
  1032.     (setq pre-loop-pseudo-steps
  1033.           (nconc pre-loop-pseudo-steps (loop-copylist* (cadr tem))))
  1034.     (cond ((or (not (loop-tequal (car loop-source-code) 'and))
  1035.                (and loop-conditionals
  1036.                     (not (loop-tassoc (cadr loop-source-code)
  1037.                                          loop-iteration-keyword-alist))))
  1038.              (setq foo (list (loop-end-testify pre-loop-pre-step-tests)
  1039.                              (loop-make-psetq pre-loop-steps)
  1040.                              (loop-end-testify pre-loop-post-step-tests)
  1041.                              (loop-make-setq pre-loop-pseudo-steps))
  1042.                    bar (list (loop-end-testify pre-step-tests)
  1043.                              (loop-make-psetq steps)
  1044.                              (loop-end-testify post-step-tests)
  1045.                              (loop-make-setq pseudo-steps)))
  1046.              (cond ((not loop-conditionals)
  1047.                       (setq loop-before-loop (nreconc foo loop-before-loop)
  1048.                             loop-after-body (nreconc bar loop-after-body)))
  1049.                    (t ((lambda (loop-conditionals)
  1050.                           (push (loop-make-conditionalization
  1051.                                    (cons 'progn (delete nil foo)))
  1052.                                 loop-before-loop))
  1053.                        (mapcar #'(lambda (x)    ;Copy parts that will get rplacd'ed
  1054.                                    (cons (car x)
  1055.                                          (mapcar #'(lambda (x) (loop-copylist* x)) (cdr x))))
  1056.                                loop-conditionals))
  1057.                       (push (loop-make-conditionalization
  1058.                                (cons 'progn (delete nil bar)))
  1059.                             loop-after-body)))
  1060.              (loop-bind-block)
  1061.              (return nil)))
  1062.     (loop-pop-source) ; flush the "AND"
  1063.     (setq entry (cond ((setq tem (loop-tassoc
  1064.                                     (car loop-source-code)
  1065.                                     loop-iteration-keyword-alist))
  1066.                          (loop-pop-source)
  1067.                          (setq last-entry tem))
  1068.                       (t last-entry)))))
  1069.  
  1070.  
  1071. ;FOR variable keyword ..args..
  1072. (defun loop-do-for ()
  1073.   (let ((var (loop-pop-source))
  1074.         (data-type? (loop-optional-type))
  1075.         (keyword (loop-pop-source))
  1076.         (first-arg nil)
  1077.         (tem nil))
  1078.     (setq first-arg (loop-get-form (list 'for var keyword)))
  1079.     (or (setq tem (loop-tassoc keyword loop-for-keyword-alist))
  1080.         (loop-simple-error
  1081.            "Unknown keyword in FOR or AS clause in LOOP"
  1082.            (list 'for var keyword)))
  1083.     (apply (cadr tem) var first-arg data-type? (cddr tem))))
  1084.  
  1085.  
  1086. (defun loop-do-repeat ()
  1087.     (let ((var (loop-make-variable
  1088.                   (loop-gentemp 'loop-repeat-)
  1089.                   (loop-get-form 'repeat) 'fixnum)))
  1090.        `((not (,(loop-typed-arith 'plusp 'fixnum) ,var))
  1091.          () ()
  1092.          (,var (,(loop-typed-arith '1- 'fixnum) ,var)))))
  1093.  
  1094.  
  1095. ; Kludge the First
  1096. (defun loop-when-it-variable ()
  1097.     (or loop-when-it-variable
  1098.         (setq loop-when-it-variable
  1099.               (loop-make-variable (loop-gentemp 'loop-it-) nil nil))))
  1100.  
  1101.  
  1102.  
  1103. (defun loop-for-equals (var val data-type?)
  1104.   (cond ((loop-tequal (car loop-source-code) 'then)
  1105.            ;FOR var = first THEN next
  1106.            (loop-pop-source)
  1107.            (loop-make-iteration-variable var val data-type?)
  1108.            `(() (,var ,(loop-get-form (list 'for var '= val 'then))) () ()
  1109.              () () () ()))
  1110.         (t (loop-make-iteration-variable var nil data-type?)
  1111.            (let ((varval (list var val)))
  1112.              (cond (loop-emitted-body?
  1113.                     (loop-emit-body (loop-make-setq varval))
  1114.                     '(() () () ()))
  1115.                    (`(() ,varval () ())))))))
  1116.  
  1117. (defun loop-for-first (var val data-type?)
  1118.     (or (loop-tequal (car loop-source-code) 'then)
  1119.         (loop-simple-error "found where THEN expected in FOR ... FIRST"
  1120.                            (car loop-source-code)))
  1121.     (loop-pop-source)
  1122.     (loop-make-iteration-variable var nil data-type?)
  1123.     `(() (,var ,(loop-get-form (list 'for var 'first val 'then))) () ()
  1124.       () (,var ,val) () ()))
  1125.  
  1126.  
  1127. (defun loop-list-stepper (var val data-type? fn)
  1128.     (let ((stepper (cond ((loop-tequal (car loop-source-code) 'by)
  1129.                             (loop-pop-source)
  1130.                             (loop-get-form (list 'for var
  1131.                                                  (if (eq fn 'car) 'in 'on)
  1132.                                                  val 'by)))
  1133.                          (t '(function cdr))))
  1134.           (var1 nil) (stepvar nil) (step nil) (et nil) (pseudo nil))
  1135.        (setq step (if (or (atom stepper)
  1136.                           (not (member (car stepper) '(quote function))))
  1137.                       `(funcall ,(setq stepvar (loop-gentemp 'loop-fn-)))
  1138.                       (list (cadr stepper))))
  1139.        (cond ((and (atom var)
  1140.                    ;; (eq (car step) 'cdr)
  1141.                    (not fn))
  1142.                 (setq var1 (loop-make-iteration-variable var val data-type?)))
  1143.              (t (loop-make-iteration-variable var nil data-type?)
  1144.                 (setq var1 (loop-make-variable
  1145.                              (loop-gentemp 'loop-list-) val nil))
  1146.                 (setq pseudo (list var (if fn (list fn var1) var1)))))
  1147.        (rplacd (last step) (list var1))
  1148.        (and stepvar (loop-make-variable stepvar stepper nil))
  1149.        (setq stepper (list var1 step) et `(null ,var1))
  1150.        (if (not pseudo) `(() ,stepper ,et () () () ,et ())
  1151.            (if (eq (car step) 'cdr) `(,et ,pseudo () ,stepper)
  1152.                `((null (setq ,@stepper)) () () ,pseudo ,et () () ,pseudo)))))
  1153.  
  1154.  
  1155. (defun loop-for-arithmetic (var val data-type? kwd)
  1156.   ; Args to loop-sequencer:
  1157.   ; indexv indexv-type variable? vtype? sequencev? sequence-type
  1158.   ; stephack? default-top? crap prep-phrases
  1159.   (loop-sequencer
  1160.      var (or data-type? #|'fixnum|#) nil nil nil nil nil nil `(for ,var ,kwd ,val)
  1161.      (cons (list kwd val)
  1162.            (loop-gather-preps
  1163.               '(from upfrom downfrom to upto downto above below by)
  1164.               nil))))
  1165.  
  1166.  
  1167. (defun loop-named-variable (name)
  1168.     (let ((tem (loop-tassoc name loop-named-variables)))
  1169.        (cond ((null tem) (loop-gentemp))
  1170.              (t (setq loop-named-variables (delete tem loop-named-variables))
  1171.                 (cdr tem)))))
  1172.  
  1173.  
  1174. ; Note:     path functions are allowed to use loop-make-variable, hack
  1175. ; the prologue, etc.
  1176. (defun loop-for-being (var val data-type?)
  1177.    ; FOR var BEING something ... - var = VAR, something = VAL.
  1178.    ; If what passes syntactically for a pathname isn't, then
  1179.    ; we trap to the DEFAULT-LOOP-PATH path;     the expression which looked like
  1180.    ; a path is given as an argument to the IN preposition.    Thus,
  1181.    ; by default, FOR var BEING EACH expr OF expr-2
  1182.    ; ==> FOR var BEING DEFAULT-LOOP-PATH IN expr OF expr-2.
  1183.    (let ((tem nil) (inclusive? nil) (ipps nil) (each? nil) (attachment nil))
  1184.      (if (or (loop-tequal val 'each) (loop-tequal val 'the))
  1185.          (setq each? 't val (car loop-source-code))
  1186.          (push val loop-source-code))
  1187.      (cond ((and (setq tem (loop-tassoc val loop-path-keyword-alist))
  1188.                  (or each? (not (loop-tequal (cadr loop-source-code)
  1189.                                                 'and))))
  1190.               ;; FOR var BEING {each} path {prep expr}..., but NOT
  1191.               ;; FOR var BEING var-which-looks-like-path AND {ITS} ...
  1192.               (loop-pop-source))
  1193.            (t (setq val (loop-get-form (list 'for var 'being)))
  1194.               (cond ((loop-tequal (car loop-source-code) 'and)
  1195.                        ;; FOR var BEING value AND ITS path-or-ar
  1196.                        (or (null each?)
  1197.                            (loop-simple-error
  1198.                               "Malformed BEING EACH clause in LOOP" var))
  1199.                        (setq ipps `((of ,val)) inclusive? t)
  1200.                        (loop-pop-source)
  1201.                        (or (loop-tmember (setq tem (loop-pop-source))
  1202.                                             '(its his her their each))
  1203.                            (loop-simple-error
  1204.                               "found where ITS or EACH expected in LOOP path"
  1205.                               tem))
  1206.                        (if (setq tem (loop-tassoc
  1207.                                         (car loop-source-code)
  1208.                                         loop-path-keyword-alist))
  1209.                            (loop-pop-source)
  1210.                            (push (setq attachment
  1211.                                        `(in ,(loop-get-form
  1212.                                               `(for ,var being \.\.\. in))))
  1213.                                  ipps)))
  1214.                     ((not (setq tem (loop-tassoc
  1215.                                        (car loop-source-code)
  1216.                                        loop-path-keyword-alist)))
  1217.                        ; FOR var BEING {each} a-r ...
  1218.                        (setq ipps (list (setq attachment (list 'in val)))))
  1219.                     (t ; FOR var BEING {each} pathname ...
  1220.                        ; Here, VAL should be just PATHNAME.
  1221.                        (loop-pop-source)))))
  1222.      (cond ((not (null tem)))
  1223.            ((not (setq tem (loop-tassoc 'default-loop-path
  1224.                                            loop-path-keyword-alist)))
  1225.               (loop-simple-error "Undefined LOOP iteration path"
  1226.                                  (cadr attachment))))
  1227.      (setq tem (funcall (cadr tem) (car tem) var data-type?
  1228.                         (nreconc ipps (loop-gather-preps (caddr tem) t))
  1229.                         inclusive? (caddr tem) (cdddr tem)))
  1230.      (and loop-named-variables
  1231.           (loop-simple-error "unused USING variables" loop-named-variables))
  1232.      ; For error continuability (if there is any):
  1233.      (setq loop-named-variables nil)
  1234.      ;; TEM is now (bindings prologue-forms . stuff-to-pass-back)
  1235.      (do ((l (car tem) (cdr l)) (x)) ((null l))
  1236.        (if (atom (setq x (car l)))
  1237.            (loop-make-iteration-variable x nil nil)
  1238.            (loop-make-iteration-variable (car x) (cadr x) (caddr x))))
  1239.      (setq loop-prologue (nconc (reverse (cadr tem)) loop-prologue))
  1240.      (cddr tem)))
  1241.  
  1242.  
  1243. (defun loop-gather-preps (preps-allowed crockp)
  1244.    (do ((token (car loop-source-code) (car loop-source-code)) (preps nil))
  1245.        (nil)
  1246.      (cond ((loop-tmember token preps-allowed)
  1247.               (push (list (loop-pop-source)
  1248.                           (loop-get-form `(for \... being \... ,token)))
  1249.                     preps))
  1250.            ((loop-tequal token 'using)
  1251.               (loop-pop-source)
  1252.               (or crockp (loop-simple-error
  1253.                             "USING used in illegal context"
  1254.                             (list 'using (car loop-source-code))))
  1255.               (do ((z (car loop-source-code) (car loop-source-code)) (tem))
  1256.                   ((atom z))
  1257.                 (and (or (atom (cdr z))
  1258.                          (not (null (cddr z)))
  1259.                          (not (symbolp (car z)))
  1260.                          (and (cadr z) (not (symbolp (cadr z)))))
  1261.                      (loop-simple-error
  1262.                         "bad variable pair in path USING phrase" z))
  1263.                 (cond ((not (null (cadr z)))
  1264.                          (and (setq tem (loop-tassoc
  1265.                                            (car z) loop-named-variables))
  1266.                               (loop-simple-error
  1267.                                  "Duplicated var substitition in USING phrase"
  1268.                                  (list tem z)))
  1269.                          (push (cons (car z) (cadr z)) loop-named-variables)))
  1270.                 (loop-pop-source)))
  1271.            (t (return (nreverse preps))))))
  1272.  
  1273. (defun loop-add-path (name data)
  1274.     (setq loop-path-keyword-alist
  1275.           (cons (cons name data)
  1276.                 (delete (loop-tassoc name loop-path-keyword-alist)
  1277.                         loop-path-keyword-alist
  1278.                         :test #'eq)))
  1279.     nil)
  1280.  
  1281.  
  1282. (defmacro define-loop-path (names &rest cruft)
  1283.   "(DEFINE-LOOP-PATH NAMES PATH-FUNCTION LIST-OF-ALLOWABLE-PREPOSITIONS
  1284. DATUM-1 DATUM-2 ...)
  1285. Defines PATH-FUNCTION to be the handler for the path(s) NAMES, which may
  1286. be either a symbol or a list of symbols.  LIST-OF-ALLOWABLE-PREPOSITIONS
  1287. contains a list of prepositions allowed in NAMES. DATUM-i are optional;
  1288. they are passed on to PATH-FUNCTION as a list."
  1289.   (setq names (if (atom names) (list names) names))
  1290.   (let ((forms (mapcar #'(lambda (name) `(loop-add-path ',name ',cruft))
  1291.                        names)))
  1292.     `(eval-when (eval load compile) ,@forms)))
  1293.  
  1294.  
  1295. (defun loop-sequencer (indexv indexv-type
  1296.                           variable? vtype?
  1297.                           sequencev? sequence-type?
  1298.                           stephack? default-top?
  1299.                           crap prep-phrases)
  1300.    (let ((endform nil) (sequencep nil) (test nil)
  1301.          (step ; Gross me out!
  1302.                (1+ (or (loop-typed-init indexv-type) 0)))
  1303.          (dir nil) (inclusive-iteration? nil) (start-given? nil) (limit-given? nil))
  1304.      (and variable? (loop-make-iteration-variable variable? nil vtype?))
  1305.      (do ((l prep-phrases (cdr l)) (prep) (form) (odir)) ((null l))
  1306.        (setq prep (caar l) form (cadar l))
  1307.        (cond ((loop-tmember prep '(of in))
  1308.                 (and sequencep (loop-simple-error
  1309.                                   "Sequence duplicated in LOOP path"
  1310.                                   (list variable? (car l))))
  1311.                 (setq sequencep t)
  1312.                 (loop-make-variable sequencev? form sequence-type?))
  1313.              ((loop-tmember prep '(from downfrom upfrom))
  1314.                 (and start-given?
  1315.                      (loop-simple-error
  1316.                         "Iteration start redundantly specified in LOOP sequencing"
  1317.                         (append crap l)))
  1318.                 (setq start-given? t)
  1319.                 (cond ((loop-tequal prep 'downfrom) (setq dir 'down))
  1320.                       ((loop-tequal prep 'upfrom) (setq dir 'up)))
  1321.                 (loop-make-iteration-variable indexv form indexv-type))
  1322.              ((cond ((loop-tequal prep 'upto)
  1323.                        (setq inclusive-iteration? (setq dir 'up)))
  1324.                     ((loop-tequal prep 'to)
  1325.                        (setq inclusive-iteration? t))
  1326.                     ((loop-tequal prep 'downto)
  1327.                        (setq inclusive-iteration? (setq dir 'down)))
  1328.                     ((loop-tequal prep 'above) (setq dir 'down))
  1329.                     ((loop-tequal prep 'below) (setq dir 'up)))
  1330.                 (and limit-given?
  1331.                      (loop-simple-error
  1332.                        "Endtest redundantly specified in LOOP sequencing path"
  1333.                        (append crap l)))
  1334.                 (setq limit-given? t)
  1335.                 (setq endform (loop-maybe-bind-form form indexv-type)))
  1336.              ((loop-tequal prep 'by)
  1337.                 (setq step (if (loop-constantp form) form
  1338.                                (loop-make-variable
  1339.                                  (loop-gentemp 'loop-step-by-)
  1340.                                  form 'fixnum))))
  1341.              (t ; This is a fatal internal error...
  1342.                 (loop-simple-error "Illegal prep in sequence path"
  1343.                                    (append crap l))))
  1344.        (and odir dir (not (eq dir odir))
  1345.             (loop-simple-error
  1346.                "Conflicting stepping directions in LOOP sequencing path"
  1347.                (append crap l)))
  1348.        (setq odir dir))
  1349.      (and sequencev? (not sequencep)
  1350.           (loop-simple-error "Missing OF phrase in sequence path" crap))
  1351.      ; Now fill in the defaults.
  1352.      (setq step (list indexv step))
  1353.      (cond ((member dir '(nil up))
  1354.               (or start-given?
  1355.                   (loop-make-iteration-variable indexv 0 indexv-type))
  1356.               (and (or limit-given?
  1357.                        (cond (default-top?
  1358.                                 (loop-make-variable
  1359.                                   (setq endform (loop-gentemp
  1360.                                                   'loop-seq-limit-))
  1361.                                   nil indexv-type)
  1362.                                 (push `(setq ,endform ,default-top?)
  1363.                                       loop-prologue))))
  1364.                    (setq test (if inclusive-iteration? '(> . args)
  1365.                                   '(>= . args))))
  1366.               (push '+ step))
  1367.            (t (cond ((not start-given?)
  1368.                        (or default-top?
  1369.                            (loop-simple-error
  1370.                               "Don't know where to start stepping"
  1371.                               (append crap prep-phrases)))
  1372.                        (loop-make-iteration-variable indexv 0 indexv-type)
  1373.                        (push `(setq ,indexv
  1374.                                     (,(loop-typed-arith '1- indexv-type)
  1375.                                      ,default-top?))
  1376.                              loop-prologue)))
  1377.               (cond ((and default-top? (not endform))
  1378.                        (setq endform (loop-typed-init indexv-type)
  1379.                              inclusive-iteration? t)))
  1380.               (and (not (null endform))
  1381.                    (setq test (if inclusive-iteration? '(< . args)
  1382.                                   '(<= . args))))
  1383.               (push '- step)))
  1384.      (and (and (numberp (caddr step)) (= (caddr step) 1))        ;Generic arith
  1385.           (rplacd (cdr (rplaca step (if (eq (car step) '+) '1+ '1-)))
  1386.                   nil))
  1387.      (rplaca step (loop-typed-arith (car step) indexv-type))
  1388.      (setq step (list indexv step))
  1389.      (setq test (loop-typed-arith test indexv-type))
  1390.      (setq test (subst (list indexv endform) 'args test))
  1391.      (and stephack? (setq stephack? `(,variable? ,stephack?)))
  1392.      `(() ,step ,test ,stephack?
  1393.        () () ,test ,stephack?)))
  1394.  
  1395.  
  1396. (defun loop-sequence-elements-path (path variable data-type
  1397.                                        prep-phrases inclusive?
  1398.                                        allowed-preps data)
  1399.     allowed-preps ; unused
  1400.     (let ((indexv (loop-named-variable 'index))
  1401.           (sequencev (loop-named-variable 'sequence))
  1402.           (fetchfun nil) (sizefun nil) (type nil) (default-var-type nil)
  1403.           (crap `(for ,variable being the ,path)))
  1404.        (cond ((not (null inclusive?))
  1405.                 (rplacd (cddr crap) `(,(cadar prep-phrases) and its ,path))
  1406.                 (loop-simple-error "Can't step sequence inclusively" crap)))
  1407.        (setq fetchfun (car data)
  1408.              sizefun (car (setq data (cdr data)))
  1409.              type (car (setq data (cdr data)))
  1410.              default-var-type (cadr data))
  1411.        (list* nil nil ; dummy bindings and prologue
  1412.               (loop-sequencer
  1413.                  indexv 'fixnum
  1414.                  variable (or data-type default-var-type)
  1415.                  sequencev type
  1416.                  `(,fetchfun ,sequencev ,indexv) `(,sizefun ,sequencev)
  1417.                  crap prep-phrases))))
  1418.  
  1419.  
  1420.  
  1421. (defmacro define-loop-sequence-path (path-name-or-names fetchfun sizefun
  1422.                                      &optional sequence-type element-type)
  1423.   "Defines a sequence iiteration path.  PATH-NAME-OR-NAMES is either an
  1424. atomic path name or a list of path names.  FETCHFUN is a function of
  1425. two arguments, the sequence and the index of the item to be fetched.
  1426. Indexing is assumed to be zero-origined.  SIZEFUN is a function of
  1427. one argument, the sequence; it should return the number of elements in
  1428. the sequence.  SEQUENCE-TYPE is the name of the data-type of the
  1429. sequence, and ELEMENT-TYPE is the name of the data-type of the elements
  1430. of the sequence."
  1431.     `(define-loop-path ,path-name-or-names
  1432.         loop-sequence-elements-path
  1433.         (of in from downfrom to downto below above by)
  1434.         ,fetchfun ,sizefun ,sequence-type ,element-type))
  1435.  
  1436.  
  1437. ;;;; Setup stuff
  1438.  
  1439.  
  1440. (mapc #'(lambda (x)
  1441.           (mapc #'(lambda (y)
  1442.                     (setq loop-path-keyword-alist
  1443.                           (cons `(,y loop-sequence-elements-path
  1444.                                   (of in from downfrom to downto
  1445.                                       below above by)
  1446.                                   ,@(cdr x))
  1447.                                 (delete (loop-tassoc
  1448.                                           y loop-path-keyword-alist)
  1449.                                         loop-path-keyword-alist
  1450.                                         :test #'eq :count 1))))
  1451.                 (car x)))
  1452.       '( ((element elements) elt length sequence)
  1453.         ;The following should be done by using ELEMENTS and type dcls...
  1454.           ((vector-element 
  1455.             vector-elements 
  1456.             array-element     ;; Backwards compatibility -- DRM
  1457.             array-elements)
  1458.            aref length vector)
  1459.           ((simple-vector-element simple-vector-elements
  1460.             simple-general-vector-element simple-general-vector-elements)
  1461.            svref simple-vector-length simple-vector)
  1462.           ((bits bit bit-vector-element bit-vector-elements)
  1463.              bit bit-vector-length bit-vector bit)
  1464.           ((simple-bit-vector-element simple-bit-vector-elements)
  1465.              sbit simple-bit-vector-length simple-bit-vector bit)
  1466.           ((character characters string-element string-elements)
  1467.            char length string string-char)
  1468.           ((simple-string-element simple-string-elements)
  1469.            schar length simple-string string-char)
  1470.         )
  1471.       )
  1472.  
  1473. ; (setf (macro-function 'lisp::loop) #'loop)
  1474. (pushnew 'loop *features*)    ;; Common-Lisp says this is correct.
  1475. (pushnew :loop *features*)    ;; But Lucid only understands this one.
  1476.  
  1477. (defun initial-value (x) x nil)
  1478. (defun variable-declarations (type &rest vars) type vars nil)
  1479.  
  1480. ; Loop exists.
  1481. (provide 'loop)
  1482.  
  1483.  
  1484.  
  1485.  
  1486.  
  1487.  
  1488.  
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.